/**********************************************************************/
/**  Copyright (c) ECC labs. 2001-2002. All Rights Reserved.		 **/
/**********************************************************************/
/*
	binword.cpp
	Mark Papazyan

*/

#include "binword.h"


ostream& operator<<(ostream& out, CBinWord& a)
{
	for(t_cnt i=a.n-1; i>=0; i--)
		(a.num>>(t_src)i& I)?out<<'1':out<<'.';
	return out;
}


istream& operator>>(istream& in, CBinWord& a)
{
	string s;
	in>>s;
	for(t_cnt i=0; i<a.n; i++)
		if(s[i]=='1')
			a.num^=(I<<i);
	return in;
}

/*self intelligent
istream& operator>>(istream& in, CBinWord& a)
{
	string s;
	in>>s;
	a.n=s.size();
	for(t_cnt i=0; i<a.n; i++)
		if(s[i]=='1')
			a.num^=(I<<i);
	return in;
}
*/


t_src CBinWord::bin2dec(char* p)
 {
 	t_src res=(t_src)0;
	t_len cnt=(t_src)0;
	while(p[cnt])
		cnt++;

	for(t_cnt i=cnt-1; i>=0; i--)
 		if(p[i]=='1') res^=(I<<(cnt-1-i));

 	return res;
 }

 t_src CBinWord::bin2dec(string& p)
 {
 	t_src res=(t_src)0;

	for(t_cnt i=0; i<p.size(); i++)
 		if(p[i]=='1') res^=(I<<(p.size()-1-i));

 	return res;
 }



//converts int to char*
 char* CBinWord::dec2bin()
 {
 	char* bin=new char[(int)n];
 	for(t_cnt i=n-1; i>=0; i--)
 		 bin[n-1-i]=(num>>i)&I?'1':'0';	//shifts and writes from the end
 	bin[n]='\0';

 	return bin;
 }


CBinWord& CBinWord::operator+=(CBinWord& a)
{
	num^=a.num;
    return *this;
}

CBinWord CBinWord::operator+(CBinWord& a)
{
    CBinWord c(a.n, a.num^num);
    return c;
}



t_len d(CBinWord a, CBinWord b)
{
	a.weight=0;
	a=a+b;
	for(t_cnt i=0; i<a.n; i++)
		a.weight+= (t_len)((a.num>>i) & I);
	return a.weight;
}




t_len CBinWord::wt()
{
	weight=0;
	for(t_cnt i=0; i<n; i++)
		weight+=(t_len)((num>>i)&I);
		return weight;
}




void CBinWord::next()
{
         t_cnt i=0;
	     t_cnt k=0;
		for(; (((3UL<<i)&num)!=(1UL<<i))&&(i<n); i++)
		{
            if(((3UL<<i)&num)==(3UL<<i))k++;
        }
     num=(((num>>(i+I))+I)<<(i+I)) | ((I<<k)-I);

}

void print(t_src a)
{
	for(int i=31; i>=0; i--)
		(a>>i&1)?cout<<'1':cout<<'.';
	cout<<'\n';
}

void CBinWord::cyclic_shift(t_len k, char where)
{
 if(where=='r')
	 num=(num>>k)|(num<<(n-k));
 else
	num=(num<<k)|(num>>(n-k));
}


void CBinWord::bit_set(t_len pos)
{
	num|=(I<<pos);
}


inline void CBinWord::bit_clear(t_len pos)
{
	num&=~(I<<pos);
}


void CBinWord::bit_swap(t_len pos1, t_len pos2)
{
	if(((num>>pos1)^(num>>pos2))&I)
		num^=((I<<pos1)^(I<<pos2)) ;
}


t_res CBinWord::is_set(t_len pos)
{
	return t_res((num>>pos)&I);
}

CBinWord& CBinWord::operator^=(CBinWord& a)
{
	*this=*this^a;
	return *this;

}

bool CBinWord::operator==(CBinWord a)
{
	return (num==a.num);
}



CBinWord CBinWord::operator^(CBinWord& a)
{
	t_cnt foo=(n-1)*a.n;
	CBinWord Ret(n*a.n);
	for(t_cnt i=n-1; i>=0; i--)
	{
		if(num>>i&I)
			Ret.num^=a.num<<foo;
		foo-=a.n;
	}

	return Ret;

}

#ifndef BORLAND
ostream& operator<<(ostream& out, u64& a)
{
	for(int i=63; i>=0; i--)
		(a>>i&(u64)I)?out<<'1':out<<'.';
	return out;
}


#ifdef WINDOWS
istream& operator>>(istream& in, u64& a)
{
	char ch;
	in.get(ch);
	a=(u64)0;
	while(ch!='\n')
	{
		a=a*(u64)10+(u64)(ch-48);
		in.get(ch);
	}
	return in;
}
#endif
#endif/*BORLAND*/
